﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Infragistics.Win;
using Infragistics.Win.UltraWinGrid;
using Litografia.BusinessComponents;
using Litografia.BusinessEntities;
using BeforeExitEditModeEventArgs = Infragistics.Win.UltraWinGrid.BeforeExitEditModeEventArgs;
using Microsoft.Practices.EnterpriseLibrary.Security;
using Nortec.Security;
using ColumnStyle = Infragistics.Win.UltraWinGrid.ColumnStyle;

namespace Litografia.UI.Procesos
{
    public partial class HojaRegistroForm : BaseForm
    {
        #region Constructors

        public HojaRegistroForm()
        {
            InitializeComponent();
            toolStrip.ItemClicked += ToolStripItemClicked;
        }

        #endregion
        
        #region Declarations

        private BEOT registro = new BEOT();
        private readonly UltraDropDown operarioDropDown = new UltraDropDown();
        private readonly UltraDropDown materialDropDown = new UltraDropDown();
        private readonly UltraDropDown maquinaDropDown = new UltraDropDown();
        private bool otLoaded;
        private bool entregaLoaded;
        private bool entregaClosed;
        private bool validForm = true;
        private bool loadingOT;

        #endregion

        #region Event Handlers

        private void RegistroOrdenTrabajoFormLoad(object sender, EventArgs e)
        {
            ConfigureToolBar(toolStrip, ToolBarButtons.Save | ToolBarButtons.Clear | ToolBarButtons.Approve | ToolBarButtons.Close);
            ConfigureGrids();
            LoadData();

            ClearControls();
            ConfigurePermissions();
        }

        private void ToolStripItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            switch ((ToolBarButtons)e.ClickedItem.Tag)
            {
                case ToolBarButtons.Save:
                    Save();
                    break;
                case ToolBarButtons.Clear:
                    ClearControls();
                    ordenTrabajoTextBox.Focus();
                    break;
                case ToolBarButtons.Approve:
                    CloseEntrega();
                    break;
                case ToolBarButtons.Close:
                    Close();
                    break;
            }
        }

        private void GridInitializeLayout(object sender, InitializeLayoutEventArgs e)
        {
            switch (e.Layout.Grid.Name)
            {
                case "acabadosGrid":
                case "prensasGrid":
                    // Oculta algunas columnas
                    e.Layout.Bands[0].Columns[registro.OTDetalle.IdColumn.ColumnName].Hidden = true;
                    e.Layout.Bands[0].Columns[registro.OTDetalle.OTEntregaIdColumn.ColumnName].Hidden = true;
                    e.Layout.Bands[0].Columns[registro.OTDetalle.OperarioIdColumn.ColumnName].Hidden = true;
                    e.Layout.Bands[0].Columns[registro.OTDetalle.AyudanteIdColumn.ColumnName].Hidden = true;
                    e.Layout.Bands[0].Columns[registro.OTDetalle.MaquinaIdColumn.ColumnName].Hidden = true;
                    e.Layout.Bands[0].Columns[registro.OTDetalle.TipoColumn.ColumnName].Hidden = true;

                    //Ancho de columnas
                    e.Layout.Bands[0].Columns[registro.OTDetalle.FechaColumn.ColumnName].Width = 90;
                    e.Layout.Bands[0].Columns[registro.OTDetalle.OperarioNombreColumn.ColumnName].Width = 170;
                    e.Layout.Bands[0].Columns[registro.OTDetalle.AyudanteNombreColumn.ColumnName].Width = 170;
                    e.Layout.Bands[0].Columns[registro.OTDetalle.MaquinaNombreColumn.ColumnName].Width = 170;
                    e.Layout.Bands[0].Columns[registro.OTDetalle.CantidadColumn.ColumnName].Width = 60;
                    e.Layout.Bands[0].Columns[registro.OTDetalle.HorasRegularColumn.ColumnName].Width = 60;
                    e.Layout.Bands[0].Columns[registro.OTDetalle.HorasExtraColumn.ColumnName].Width = 60;
                    e.Layout.Bands[0].Columns[registro.OTDetalle.HorasDobleColumn.ColumnName].Width = 60;
                    e.Layout.Bands[0].Columns[registro.OTDetalle.DescripcionColumn.ColumnName].Width = 200;

                    // Asocia los dropdowns
                    e.Layout.Bands[0].Columns[registro.OTDetalle.OperarioNombreColumn.ColumnName].Style = ColumnStyle.DropDownList;
                    e.Layout.Bands[0].Columns[registro.OTDetalle.AyudanteNombreColumn.ColumnName].Style = ColumnStyle.DropDownList;
                    e.Layout.Bands[0].Columns[registro.OTDetalle.MaquinaNombreColumn.ColumnName].Style = ColumnStyle.DropDownList;
                    e.Layout.Bands[0].Columns[registro.OTDetalle.OperarioNombreColumn.ColumnName].ValueList = operarioDropDown;
                    e.Layout.Bands[0].Columns[registro.OTDetalle.AyudanteNombreColumn.ColumnName].ValueList = operarioDropDown;
                    e.Layout.Bands[0].Columns[registro.OTDetalle.MaquinaNombreColumn.ColumnName].ValueList = maquinaDropDown;

                    if (e.Layout.Grid.Name == "acabadosGrid")
                    {
                        e.Layout.Bands[0].Columns[registro.OTDetalle.DescripcionColumn.ColumnName].Hidden = true;
                        e.Layout.AutoFitStyle = AutoFitStyle.ResizeAllColumns;
                    }
                    break;

                case "acabadosMaterialesGrid":
                case "prensasMaterialesGrid":
                    // Oculta algunas columnas
                    e.Layout.Bands[0].Columns[registro.OTMaterial.IdColumn.ColumnName].Hidden = true;
                    e.Layout.Bands[0].Columns[registro.OTMaterial.OTEntregaIdColumn.ColumnName].Hidden = true;
                    e.Layout.Bands[0].Columns[registro.OTMaterial.OperarioIdColumn.ColumnName].Hidden = true;
                    e.Layout.Bands[0].Columns[registro.OTMaterial.TipoColumn.ColumnName].Hidden = true;

                    //Ancho de columnas
                    e.Layout.Bands[0].Columns[registro.OTMaterial.FechaColumn.ColumnName].Width = 100;
                    e.Layout.Bands[0].Columns[registro.OTMaterial.MaterialNombreColumn.ColumnName].Width = 300;
                    e.Layout.Bands[0].Columns[registro.OTMaterial.CantidadColumn.ColumnName].Width = 100;
                    e.Layout.Bands[0].Columns[registro.OTMaterial.OperarioIdColumn.ColumnName].Width = 200;
                    e.Layout.Bands[0].Columns[registro.OTMaterial.DepartamentoColumn.ColumnName].Width = 200;

                    // Asocia los dropdowns
                    e.Layout.Bands[0].Columns[registro.OTMaterial.MaterialNombreColumn.ColumnName].Style = ColumnStyle.DropDownList;
                    e.Layout.Bands[0].Columns[registro.OTMaterial.OperarioNombreColumn.ColumnName].Style = ColumnStyle.DropDownList;
                    e.Layout.Bands[0].Columns[registro.OTMaterial.MaterialNombreColumn.ColumnName].ValueList = materialDropDown;
                    e.Layout.Bands[0].Columns[registro.OTMaterial.OperarioNombreColumn.ColumnName].ValueList = operarioDropDown;

                    if (e.Layout.Grid.Name == "acabadosMaterialesGrid")
                    {
                        e.Layout.Bands[0].Columns[registro.OTMaterial.OperarioNombreColumn.ColumnName].Hidden = true;
                        e.Layout.AutoFitStyle = AutoFitStyle.ResizeAllColumns;
                    }
                    else
                    {
                        e.Layout.Bands[0].Columns[registro.OTMaterial.DepartamentoColumn.ColumnName].Hidden = true;
                    }

                    e.Layout.Bands[0].Columns[registro.OTMaterial.MaterialIdColumn.ColumnName].CellActivation = Activation.NoEdit;

                    e.Layout.AutoFitStyle = AutoFitStyle.ResizeAllColumns;
                    break;
            }
            FormatNumbers(e.Layout.Grid);
        }

        private void GridBeforeExitEditMode(object sender, BeforeExitEditModeEventArgs e)
        {
            UltraGridCell cell = null;
            Type cellType = null;

            if (acabadosGrid.ActiveCell != null)
            {
                cell = acabadosGrid.ActiveCell;
                cellType = registro.OTDetalle.Columns[cell.Column.Index].DataType;
            }
            else if (prensasGrid.ActiveCell != null)
            {
                cell = prensasGrid.ActiveCell;
                cellType = registro.OTDetalle.Columns[cell.Column.Index].DataType;
            }
            else if (acabadosMaterialesGrid.ActiveCell != null)
            {
                cell = acabadosMaterialesGrid.ActiveCell;
                cellType = registro.OTMaterial.Columns[cell.Column.Index].DataType;
            }
            else if (prensasMaterialesGrid.ActiveCell != null)
            {
                cell = prensasMaterialesGrid.ActiveCell;
                cellType = registro.OTMaterial.Columns[cell.Column.Index].DataType;
            }
            else if (gastosGrid.ActiveCell != null)
            {
                cell = gastosGrid.ActiveCell;
                cellType = registro.Gasto.Columns[cell.Column.Index].DataType;
            }

            if (cell != null)
            {
                switch (cellType.ToString())
                {
                    case "System.Decimal":
                        decimal dummy;
                        if (!string.IsNullOrEmpty(cell.Text) && !decimal.TryParse(cell.Text, out dummy))
                        {
                            ShowError("El valor ingresado en el campo \"" + cell.Column.Header.Caption + "\" no es válido");
                            e.Cancel = true;
                        }
                        break;
                }
            }
        }

        private void GridBeforeRowUpdate(object sender, CancelableRowEventArgs e)
        {
            var currentGridName = ((UltraGrid)sender).Name;

            switch (currentGridName)
            {
                case "acabadosGrid":
                case "prensasGrid":
                    if (e.Row.Cells[registro.OTDetalle.FechaColumn.ColumnName].Value == Convert.DBNull)
                    {
                        ShowError("Debe seleccionar la Fecha para actualizar un registro");
                        e.Cancel = true;
                    }
                    else if (e.Row.Cells[registro.OTDetalle.OperarioNombreColumn.ColumnName].Value == Convert.DBNull &&
                         e.Row.Cells[registro.OTDetalle.AyudanteNombreColumn.ColumnName].Value == Convert.DBNull)
                    {
                        ShowError("Debe seleccionar ya sea un Operario o un Ayudante para actualizar un registro");
                        e.Cancel = true;
                    }
                    else if (e.Row.Cells[registro.OTDetalle.MaquinaNombreColumn.ColumnName].Value == Convert.DBNull)
                    {
                        ShowError("Debe seleccionar la Máquina o Proceso para actualizar un registro");
                        e.Cancel = true;
                    }
                    else if (e.Row.Cells[registro.OTDetalle.CantidadColumn.ColumnName].Value == Convert.DBNull)
                    {
                        ShowError("Debe ingresar la Cantidad para actualizar un registro");
                        e.Cancel = true;
                    }
                    else if (e.Row.Cells[registro.OTDetalle.HorasRegularColumn.ColumnName].Value == Convert.DBNull &&
                             e.Row.Cells[registro.OTDetalle.HorasExtraColumn.ColumnName].Value == Convert.DBNull &&
                             e.Row.Cells[registro.OTDetalle.HorasDobleColumn.ColumnName].Value == Convert.DBNull)
                    {
                        ShowError("Debe ingresar las Horas para actualizar un registro");
                        e.Cancel = true;
                    }
                    break;

                case "acabadosMaterialesGrid":
                case "prensasMaterialesGrid":
                    if (e.Row.Cells[registro.OTMaterial.FechaColumn.ColumnName].Value == Convert.DBNull)
                    {
                        ShowError("Debe seleccionar la Fecha para actualizar un registro");
                        e.Cancel = true;
                    }
                    else if (e.Row.Cells[registro.OTMaterial.MaterialNombreColumn.ColumnName].Value == Convert.DBNull)
                    {
                        ShowError("Debe seleccionar el Material para actualizar un registro");
                        e.Cancel = true;
                    }
                    else if (e.Row.Cells[registro.OTMaterial.CantidadColumn.ColumnName].Value == Convert.DBNull)
                    {
                        ShowError("Debe ingresar el Cantidad para actualizar un registro");
                        e.Cancel = true;
                    }
                    else if (currentGridName == "prensasMaterialesGrid" && e.Row.Cells[registro.OTMaterial.OperarioNombreColumn.ColumnName].Value == Convert.DBNull)
                    {
                        ShowError("Debe seleccionar el Operario para actualizar un registro");
                        e.Cancel = true;
                    }
                    break;
            }
            validForm = !e.Cancel;
        }

        private void GridLeave(object sender, EventArgs e)
        {
            if (acabadosGrid.ActiveRow != null)
            {
                acabadosGrid.PerformAction(UltraGridAction.ExitEditMode, true, true);
                GridBeforeRowUpdate(acabadosGrid, new CancelableRowEventArgs(acabadosGrid.ActiveRow));
            }
            else if (prensasGrid.ActiveRow != null)
            {
                prensasGrid.PerformAction(UltraGridAction.ExitEditMode, true, true);
                GridBeforeRowUpdate(prensasGrid, new CancelableRowEventArgs(prensasGrid.ActiveRow));
            }
            else if (acabadosMaterialesGrid.ActiveRow != null)
            {
                acabadosMaterialesGrid.PerformAction(UltraGridAction.ExitEditMode, true, true);
                GridBeforeRowUpdate(acabadosMaterialesGrid, new CancelableRowEventArgs(acabadosMaterialesGrid.ActiveRow));
            }
            else if (prensasMaterialesGrid.ActiveRow != null)
            {
                prensasMaterialesGrid.PerformAction(UltraGridAction.ExitEditMode, true, true);
                GridBeforeRowUpdate(prensasMaterialesGrid, new CancelableRowEventArgs(prensasMaterialesGrid.ActiveRow));
            }
        }

        private void GastosGridInitializeLayout(object sender, InitializeLayoutEventArgs e)
        {
            // Initial setup
            foreach (var col in e.Layout.Bands[0].Columns)
            {
                col.Header.Appearance.TextHAlign = HAlign.Center;
                col.CellActivation = Activation.ActivateOnly;
                col.Hidden = true;
            }

            if (e.Layout.Bands[1] != null)
                e.Layout.Bands[1].Hidden = true;

            e.Layout.Bands[0].Columns[registro.Gasto.ConceptoColumn.ColumnName].Hidden = false;
            e.Layout.Bands[0].Columns[registro.Gasto.MontoColumn.ColumnName].Hidden = false;
            e.Layout.Bands[0].Columns[registro.Gasto.SeleccionadoColumn.ColumnName].Hidden = false;

            //Ancho de columnas
            e.Layout.Bands[0].Columns[registro.Gasto.ConceptoColumn.ColumnName].Width = 300;
            e.Layout.Bands[0].Columns[registro.Gasto.MontoColumn.ColumnName].Width = 100;
            e.Layout.Bands[0].Columns[registro.Gasto.SeleccionadoColumn.ColumnName].Width = 30;
            e.Layout.AutoFitStyle = AutoFitStyle.ResizeAllColumns;

            //Alineamiento y edicion
            e.Layout.Bands[0].Columns[registro.Gasto.MontoColumn.ColumnName].CellAppearance.TextHAlign = HAlign.Right;
            e.Layout.Bands[0].Columns[registro.Gasto.SeleccionadoColumn.ColumnName].CellActivation = Activation.AllowEdit;
            e.Layout.Bands[0].Columns[registro.Gasto.MontoColumn.ColumnName].CellActivation = Activation.AllowEdit;

            // Formato y orden
            e.Layout.Bands[0].Columns[registro.Gasto.SeleccionadoColumn.ColumnName].Header.VisiblePosition = 1;

            gastosGrid.DisplayLayout.GroupByBox.Prompt = GridGroupBoxText;

            FormatNumbers(e.Layout.Grid);
        }

        private void OrdenTrabajoTextBoxValidated(object sender, EventArgs e)
        {
            if (!loadingOT)
                GetOT();
        }

        private void OrdenTrabajoTextBoxKeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.Enter)
                GetOT();
        }

        private static void GridKeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.Return)
                e.Handled = true;
        }

        private void GridAfterCellUpdate(object sender, CellEventArgs e)
        {
            if (e.Cell.Column.Key == registro.OTMaterial.MaterialNombreColumn.ColumnName)
                e.Cell.Row.Cells[registro.OTMaterial.MaterialIdColumn.ColumnName].Value = e.Cell.Value;
        }

        #endregion

        #region Methods: Non-Public

        private void ConfigurePermissions()
        {
            var authProvider = AuthorizationFactory.GetAuthorizationProvider();
            if (!authProvider.Authorize(NortecMembership.Principal, Privilegios.IngresarDatos))
                tabControl1.TabPages.Remove(gastosTabPage);

            var enableApply = authProvider.Authorize(NortecMembership.Principal, Privilegios.TerminarOT) && entregaLoaded && !entregaClosed;
            ToggleButton(toolStrip, ToolBarButtons.Approve, enableApply);
        }

        private void ClearControls()
        {
            otLoaded = false;
            entregaLoaded = false;
            entregaClosed = false;
            acabadosGrid.DataSource = new BEOT.OTDetalleDataTable();
            prensasGrid.DataSource = new BEOT.OTDetalleDataTable();
            acabadosMaterialesGrid.DataSource = new BEOT.OTMaterialDataTable();
            prensasMaterialesGrid.DataSource = new BEOT.OTMaterialDataTable();
            entregasListView.Items.Clear();

            registro.OTGasto.RejectChanges();
            registro.Gasto.RejectChanges();
            BindGastos();

            ClearControls(Controls);
            EnableDisableControls();
            tabControl1.SelectedTab = acabadosTabPage;
            ordenTrabajoTextBox.Focus();
            ordenTrabajoTextBox.Focus();
            Refresh();
        }

        private void LoadData()
        {
            registro = BCOT.GetParametricData();
            BindDropDowns();
            BindGastos();
        }

        private void BindGastos()
        {
            registro.Gasto.RejectChanges();
            gastosGrid.DataSource = registro.Gasto;
            gastosGrid.Refresh();
        }

        private void BindDropDowns()
        {
            operarioDropDown.DisplayMember = registro.Operario.NombreColumn.ColumnName;
            operarioDropDown.ValueMember = registro.Operario.IdColumn.ColumnName;
            operarioDropDown.SetDataBinding(registro, registro.Operario.TableName);
            operarioDropDown.DataSource = registro;
            operarioDropDown.DisplayLayout.Bands[0].Columns[0].Hidden = true;
            operarioDropDown.DisplayLayout.Bands[0].Columns[1].Width = 200;

            materialDropDown.DisplayMember = registro.Material.NombreColumn.ColumnName;
            materialDropDown.ValueMember = registro.Material.IdColumn.ColumnName;
            materialDropDown.SetDataBinding(registro, registro.Material.TableName);
            materialDropDown.DataSource = registro;
            materialDropDown.DisplayLayout.Bands[0].Columns[0].Width = 150;
            materialDropDown.DisplayLayout.Bands[0].Columns[1].Width = 300;

            maquinaDropDown.DisplayMember = registro.Maquina.NombreColumn.ColumnName;
            maquinaDropDown.ValueMember = registro.Maquina.IdColumn.ColumnName;
            maquinaDropDown.SetDataBinding(registro, registro.Maquina.TableName);
            maquinaDropDown.DataSource = registro;
            maquinaDropDown.DisplayLayout.Bands[0].Columns[0].Hidden = true;
            maquinaDropDown.DisplayLayout.Bands[0].Columns[1].Width = 300;
        }

        private void ConfigureGrid(UltraGrid grid)
        {
            grid.InitializeLayout += GridInitializeLayout;
            grid.BeforeExitEditMode += GridBeforeExitEditMode;
            grid.BeforeRowUpdate += GridBeforeRowUpdate;
            grid.AfterCellUpdate += GridAfterCellUpdate;
            grid.Leave += GridLeave;
        }

        private void ConfigureGrids()
        {
            ConfigureGrid(acabadosGrid);
            ConfigureGrid(prensasGrid);
            ConfigureGrid(acabadosMaterialesGrid);
            ConfigureGrid(prensasMaterialesGrid);
        }

        private void Save()
        {
            try
            {
                Cursor.Current = Cursors.WaitCursor;
                toolStrip.Focus();
                if (validForm)
                {
                    var toSave = Pack();
                    BCOT.Save(toSave);
                    ClearControls();
                    ShowConfirmation("La Orden de Trabajo fue guardada exitosamente");
                }
            }
            catch (Exception ex)
            {
                DisplayError("No se pudo guardar la información.", ex);
            }
            finally
            {
                Cursor.Current = Cursors.Default;
            }
        }

        private BEOT Pack()
        {
            var ordenTrabajo = new BEOT { EnforceConstraints = false };
            var ot = ordenTrabajo.OrdenTrabajo.NewOrdenTrabajoRow();
            CloneDataRow(registro.OrdenTrabajo[0], ot);
            ordenTrabajo.OrdenTrabajo.AddOrdenTrabajoRow(ot);
            var entrega = ordenTrabajo.OTEntrega.NewOTEntregaRow();
            CloneDataRow(GetCurrentEntrega(), entrega);
            ordenTrabajo.OTEntrega.AddOTEntregaRow(entrega);
            
            entrega.EstadoId = (int)OTEstado.EnProceso;
            ot.EstadoId = (int)OTEstado.EnProceso;

            if (!string.IsNullOrEmpty(manoObraTextBox.Text))
                entrega.ManoObraIndirecta = Convert.ToDecimal(manoObraTextBox.Text);

            if (!string.IsNullOrEmpty(unidadesProducidasTextBox.Text))
                entrega.UnidadesProducidas = Convert.ToDecimal(unidadesProducidasTextBox.Text);

            // Detalles (Conceptos)
            foreach (var row in acabadosGrid.Rows)
            {
                if (!row.IsAddRow)
                    ordenTrabajo.OTDetalle.AddOTDetalleRow(PackDetalle(ordenTrabajo, acabadosGrid, row));
            }
            foreach (var row in prensasGrid.Rows)
            {
                if (!row.IsAddRow)
                    ordenTrabajo.OTDetalle.AddOTDetalleRow(PackDetalle(ordenTrabajo, prensasGrid, row));
            }

            // Materiales
            foreach (var row in acabadosMaterialesGrid.Rows)
            {
                if (!row.IsAddRow)
                    ordenTrabajo.OTMaterial.AddOTMaterialRow(PackMaterial(ordenTrabajo, acabadosMaterialesGrid, row));
            }

            foreach (var row in prensasMaterialesGrid.Rows)
            {
                if (!row.IsAddRow)
                    ordenTrabajo.OTMaterial.AddOTMaterialRow(PackMaterial(ordenTrabajo, prensasMaterialesGrid, row));
            }

            // Gastos
            BEOT.OTGastoRow gasto;
            gastosGrid.Refresh();
            foreach (var row in gastosGrid.Rows)
            {
                if (Convert.ToBoolean(row.Cells[ordenTrabajo.Gasto.SeleccionadoColumn.ColumnName].Value))
                {
                    gasto = ordenTrabajo.OTGasto.NewOTGastoRow();
                    gasto.GastoId = Convert.ToInt32(row.Cells[ordenTrabajo.Gasto.IdColumn.ColumnName].Value);
                    gasto.Monto = Convert.ToInt32(row.Cells[ordenTrabajo.Gasto.MontoColumn.ColumnName].Value);
                    ordenTrabajo.OTGasto.AddOTGastoRow(gasto);
                }
            }
            return ordenTrabajo;
        }

        private BEOT.OTDetalleRow PackDetalle(BEOT ordenTrabajo, Control grid, UltraGridRow row)
        {
            var detalle = ordenTrabajo.OTDetalle.NewOTDetalleRow();
            detalle.OTEntregaId = ordenTrabajo.OTEntrega[0].Id;
            detalle.Fecha = Convert.ToDateTime(row.Cells[registro.OTDetalle.FechaColumn.ColumnName].Value);
            
            if (row.Cells[registro.OTDetalle.AyudanteNombreColumn.ColumnName].Value != Convert.DBNull)
                detalle.AyudanteId = Convert.ToInt32(row.Cells[registro.OTDetalle.AyudanteNombreColumn.ColumnName].Value);

            if (row.Cells[registro.OTDetalle.MaquinaNombreColumn.ColumnName].Value != Convert.DBNull)
                detalle.MaquinaId = Convert.ToInt32(row.Cells[registro.OTDetalle.MaquinaNombreColumn.ColumnName].Value);

            if (row.Cells[registro.OTDetalle.OperarioNombreColumn.ColumnName].Value != Convert.DBNull)
                detalle.OperarioId = Convert.ToInt32(row.Cells[registro.OTDetalle.OperarioNombreColumn.ColumnName].Value);

            if (row.Cells[registro.OTDetalle.CantidadColumn.ColumnName].Value != Convert.DBNull)
                detalle.Cantidad = Convert.ToDecimal(row.Cells[registro.OTDetalle.CantidadColumn.ColumnName].Value);

            if (row.Cells[registro.OTDetalle.HorasRegularColumn.ColumnName].Value != Convert.DBNull)
                detalle.HorasRegular = Convert.ToDecimal(row.Cells[registro.OTDetalle.HorasRegularColumn.ColumnName].Value);

            if (row.Cells[registro.OTDetalle.HorasExtraColumn.ColumnName].Value != Convert.DBNull)
                detalle.HorasExtra = Convert.ToDecimal(row.Cells[registro.OTDetalle.HorasExtraColumn.ColumnName].Value);

            if (row.Cells[registro.OTDetalle.HorasDobleColumn.ColumnName].Value != Convert.DBNull)
                detalle.HorasDoble = Convert.ToDecimal(row.Cells[registro.OTDetalle.HorasDobleColumn.ColumnName].Value);

            if (grid.Name == acabadosGrid.Name)
            {
                detalle.Tipo = "A";
            }
            else if (grid.Name == prensasGrid.Name)
            {
                detalle.Tipo = "P";
                detalle.Descripcion = row.Cells[registro.OTDetalle.DescripcionColumn.ColumnName].Value.ToString();
            }
            return detalle;
        }

        private BEOT.OTMaterialRow PackMaterial(BEOT ordenTrabajo, Control grid, UltraGridRow row)
        {
            var material = ordenTrabajo.OTMaterial.NewOTMaterialRow();
            material.OTEntregaId = ordenTrabajo.OTEntrega[0].Id;
            material.Cantidad = Convert.ToDecimal(row.Cells[registro.OTMaterial.CantidadColumn.ColumnName].Value);
            material.Fecha = Convert.ToDateTime(row.Cells[registro.OTMaterial.FechaColumn.ColumnName].Value);
            material.MaterialId = Convert.ToString(row.Cells[registro.OTMaterial.MaterialNombreColumn.ColumnName].Value);

            if (grid.Name == acabadosMaterialesGrid.Name)
            {
                material.Tipo = "A";
                if (row.Cells[registro.OTMaterial.DepartamentoColumn.ColumnName].Value != Convert.DBNull)
                    material.Departamento = row.Cells[registro.OTMaterial.DepartamentoColumn.ColumnName].Value.ToString();
            }
            else if (grid.Name == prensasMaterialesGrid.Name)
            {
                material.Tipo = "P";
                material.OperarioId = Convert.ToInt32(row.Cells[registro.OTMaterial.OperarioNombreColumn.ColumnName].Value);
            }
            return material;
        }

        private void CloseEntrega()
        {
            if (entregaLoaded)
            {
                if (ShowQuestion("¿Está seguro de cerrar la Entrega actual?\n\rNo podrá hacer más modificaciones en el futuro"))
                {
                    var toSave = Pack();
                    BCOT.Save(toSave);
                    BCOT.CloseEntrega(toSave.OTEntrega[0].Id);
                    ClearControls();
                    ShowConfirmation("La Entrega fue cerrada exitosamente");
                }
            }
        }

        private void EnableDisableControls()
        {
            ordenTrabajoTextBox.Enabled = !otLoaded;
            manoObraTextBox.Enabled = entregaLoaded && !entregaClosed;
            unidadesProducidasTextBox.Enabled = entregaLoaded && !entregaClosed;

            if (entregaLoaded && !entregaClosed)
            {
                acabadosGrid.DisplayLayout.Override.AllowUpdate = DefaultableBoolean.True;
                acabadosMaterialesGrid.DisplayLayout.Override.AllowUpdate = DefaultableBoolean.True;
                prensasGrid.DisplayLayout.Override.AllowUpdate = DefaultableBoolean.True;
                prensasMaterialesGrid.DisplayLayout.Override.AllowUpdate = DefaultableBoolean.True;
                gastosGrid.DisplayLayout.Override.AllowUpdate = DefaultableBoolean.True;
            }
            else
            {
                acabadosGrid.DisplayLayout.Override.AllowUpdate = DefaultableBoolean.False;
                acabadosMaterialesGrid.DisplayLayout.Override.AllowUpdate = DefaultableBoolean.False;
                prensasGrid.DisplayLayout.Override.AllowUpdate = DefaultableBoolean.False;
                prensasMaterialesGrid.DisplayLayout.Override.AllowUpdate = DefaultableBoolean.False;
                gastosGrid.DisplayLayout.Override.AllowUpdate = DefaultableBoolean.False;
            }

            ToggleButton(toolStrip, ToolBarButtons.Save, entregaLoaded && !entregaClosed);
            ToggleButton(toolStrip, ToolBarButtons.Clear, otLoaded);
            ToggleButton(toolStrip, ToolBarButtons.Approve, entregaLoaded && !entregaClosed);
        }

        private void GetOT()
        {
            loadingOT = true;
            var numeroOT = ordenTrabajoTextBox.Text;
            ordenTrabajoTextBox.Text = "";
            if (!string.IsNullOrEmpty(numeroOT))
            {
                BCOT.Get(numeroOT, registro);
                if (registro.OrdenTrabajo.Count == 0)
                    ShowConfirmation("La Orden de Trabajo no existe.");
                else if (registro.OrdenTrabajo[0].EstadoId == (int)OTEstado.Abierta)
                    ShowConfirmation("La Orden de Trabajo \"" + numeroOT + "\" tiene estado \"Abierta\".\r\n" +
                                     "Para poder ingresar datos debe ser puesta \"En Proceso\" previamente en el registro de la cotización.");
                else
                {
                    UnPackOT();
                    LoadEntregasList();
                    EnableDisableControls();
                }
            }
            loadingOT = false;
        }

        private void LoadEntregasList()
        {
            entregasListView.Items.Clear();
            foreach (var entrega in registro.OTEntrega)
            {
                var fechaInicial = entrega.IsFechaInicialNull() ? "" : entrega.FechaInicial.ToString("dd/MM/yyyy");
                var fechaFinal = entrega.IsFechaFinalNull() ? "" : entrega.FechaFinal.ToString("dd/MM/yyyy");
                var solicitadas = entrega.IsUnidadesSolicitadasNull() ? "" : entrega.UnidadesSolicitadas.ToString("#,##0.00");

                var item = entregasListView.Items.Add(entrega.Orden.ToString());
                item.SubItems.Add(entrega.EstadoNombre);
                item.SubItems.Add(fechaInicial);
                item.SubItems.Add(fechaFinal);
                item.SubItems.Add(solicitadas);
            }
        }

        private void UnPackOT()
        {
            var ot = registro.OrdenTrabajo[0];
            ordenTrabajoTextBox.Text = ot.NumeroOT;

            if (!ot.IsClienteIdNull())
                clienteLabel.Text = ot.ClienteNombre;

            if (!ot.IsProductoIdNull())
                productoLabel.Text = ot.ProductoNombre;

            if (!ot.IsCantidadNull())
                cantidadLabel.Text = ot.Cantidad.ToString("#,##0.00");

            otLoaded = true;
        }

        private void UnPackEntrega(BEOT.OTEntregaRow entrega)
        {
            entregaClosed = entrega.EstadoId == (int)OTEstado.Cerrada;
            entregaLoaded = true;
            EnableDisableControls();
            
            unidadesProducidasTextBox.Text = !entrega.IsUnidadesProducidasNull() ? entrega.UnidadesProducidas.ToString("#,##0.00") : "";
            manoObraTextBox.Text = !entrega.IsManoObraIndirectaNull() ? entrega.ManoObraIndirecta.ToString("#,##0.00") : "";
            acabadosGrid.DataSource = GetDetallesTable(registro.OTDetalle, "A", entrega.Id);
            acabadosMaterialesGrid.DataSource = GetMaterialesTable(registro.OTMaterial, "A", entrega.Id);
            prensasGrid.DataSource = GetDetallesTable(registro.OTDetalle, "P", entrega.Id);
            prensasMaterialesGrid.DataSource = GetMaterialesTable(registro.OTMaterial, "P", entrega.Id);
            BindGastos();

            foreach (var row in entrega.GetOTGastoRows())
            {
                foreach (var gastosRow in gastosGrid.Rows)
                {
                    var gastoId = int.Parse(gastosRow.Cells[registro.Gasto.IdColumn.ColumnName].Value.ToString());
                    if (row.GastoId == gastoId && row.OTEntregaId == entrega.Id)
                    {
                        gastosRow.Cells[registro.Gasto.SeleccionadoColumn.ColumnName].Value = true;
                        gastosRow.Cells[registro.Gasto.MontoColumn.ColumnName].Value = row.Monto;
                        break;
                    }
                }
            }
        }

        private void EntregasListViewSelectedIndexChanged(object sender, EventArgs e)
        {
            var entrega = GetCurrentEntrega();
            if (entrega != null)
                UnPackEntrega(entrega);
        }

        private BEOT.OTEntregaRow GetCurrentEntrega()
        {
            var item = entregasListView.FocusedItem;
            if (item != null)
                return GetEntrega(int.Parse(item.Text));
            return null;
        }

        private BEOT.OTEntregaRow GetEntrega(int entregaOrder)
        {
            return registro.OTEntrega.FirstOrDefault(entrega => entrega.Orden == entregaOrder);
        }

        private static BEOT.OTDetalleDataTable GetDetallesTable(IEnumerable<BEOT.OTDetalleRow> source, string tipo, int entregaId)
        {
            var result = new BEOT.OTDetalleDataTable();
            foreach (var row in source)
            {
                if (row.Tipo == tipo && row.OTEntregaId == entregaId)
                {
                    var newRow = result.NewOTDetalleRow();
                    CloneDataRow(row, newRow);
                    result.AddOTDetalleRow(newRow);
                }
            }
            return result;
        }

        private static BEOT.OTMaterialDataTable GetMaterialesTable(IEnumerable<BEOT.OTMaterialRow> source, string tipo, int entregaId)
        {
            var result = new BEOT.OTMaterialDataTable();
            foreach (var row in source)
            {
                if (row.Tipo == tipo && row.OTEntregaId == entregaId)
                {
                    var newRow = result.NewOTMaterialRow();
                    CloneDataRow(row, newRow);
                    result.AddOTMaterialRow(newRow);
                }
            }
            return result;
        }

        #endregion
    }
}
